﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System.Linq;
using ScrumTable.BL.DM.DataManagement;
using ScrumTable.Common.Collections;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ScrumTable.DL.Data.Generic.Cache;
using ScrumTable.DL.Data.Generic.Test;
using ScrumTable.DL.Data.Local.Test;
using ScrumTable.DL.Data.Schema.ScrumTableV1;

#endregion

namespace ScrumTable.BL.DM.Test.DataManagement
{


    /// <summary>
    /// This is the test class for UserStory class.
    /// </summary>
    [TestClass]
    public class UserStoryTest : ScrumItemTest<UserStory, UserStorySchema>
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private ScrumState ActiveState { get { return ToTest.ItemType.StateMappings[Resources.UserStoryActiveState]; } }
        private ScrumState ClosedState { get { return ToTest.ItemType.StateMappings[Resources.UserStoryClosedState]; } }
        private ScrumState InProgressState { get { return ToTest.ItemType.StateMappings[Resources.UserStoryInProgressState]; } }
        private ScrumState ToVerifyState { get { return ToTest.ItemType.StateMappings[Resources.UserStoryToVerifyState]; } }

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        /// <summary>
        /// Gets the default instance to test.
        /// </summary>
        protected override UserStory ToTest
        {
            get { return Context.Projects[Resources.Project1Id].Stories[Resources.UserStory1Id]; }
        }

        #endregion

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new UserStoryTest instance.
        /// </summary>
        public UserStoryTest()
        {
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Use TestInitialize to run code before running each test .
        /// </summary>
        [TestInitialize]
        public override void TestInitialize()
        {
            base.TestInitialize();
        }

        /// <summary>
        /// Use TestCleanup to run code after each test has run.
        /// </summary>
        [TestCleanup]
        public override void TestCleanup()
        {
            base.TestCleanup();
        }

        [TestMethod]
        public void TestValueChangeOnDL()
        {
            TestValueChangeWithEventOnDL(DataObjectSchema.MemberId, Resources.FullMember2IdChain, "AssignedMember");
            TestValueChangeWithEventOnDL(DataObjectSchema.Description, "[New Description]");
            TestValueChangeWithEventOnDL(DataObjectSchema.Name, "[New Name]");
            TestValueChangeWithEventOnDL(DataObjectSchema.Ranking, -15.6);
            TestValueChangeWithEventOnDL(DataObjectSchema.Ranking, 5.6);
            TestValueChangeWithEventOnDL(DataObjectSchema.Ranking, 0.0);
            TestValueChangeWithEventOnDL(DataObjectSchema.Ranking, null);
            TestValueChangeWithEventOnDL(DataObjectSchema.StoryPoints, -42.65);
            TestValueChangeWithEventOnDL(DataObjectSchema.StoryPoints, 22.65);
            TestValueChangeWithEventOnDL(DataObjectSchema.StoryPoints, 0.0);
            TestValueChangeWithEventOnDL(DataObjectSchema.StoryPoints, null);
            TestValueChangeWithEventOnDL(DataObjectSchema.State, ClosedState.Name);
            
            TestValueChangeWithEventOnDL(
                DataObjectSchema[TestFieldDefinitionSet.RiskFieldName],
                ToTest.ItemType.FieldMeta.TryGetByName(TestFieldDefinitionSet.RiskFieldName).AllowedValues.ToEnumerable().Second());
            TestValueChangeWithEventOnDL(
                DataObjectSchema[TestFieldDefinitionSet.RiskFieldName],
                null);
        }

        [TestMethod]
        public void TestValueChangeOnDM()
        {
            TestValueChangeWithEventOnDM("Ranking", -50.0);
            TestValueChangeWithEventOnDM("Ranking", 0.0);
            TestValueChangeWithEventOnDM("Ranking", 5.6);
            TestValueChangeWithEventOnDM("Ranking", null);
            TestValueChangeWithEventOnDM("StoryPoints", -412.51);
            TestValueChangeWithEventOnDM("StoryPoints", 12.51);
            TestValueChangeWithEventOnDM("StoryPoints", 0.0);
            TestValueChangeWithEventOnDM("StoryPoints", null);
            TestValueChangeWithEventOnDM("State", ClosedState);
        }

        [TestMethod]
        public void TestParentEvent()
        {
            UserStory testObject = ToTest;
            Iteration newParent1 = Context.Projects[Resources.Project1Id].Iterations[Resources.Iteration1Id];
            Iteration newParent2 = Context.Projects[Resources.Project1Id].Iterations[Resources.Iteration2Id];

            testObject.FireParentChangedEvent = false;
            TestAssertParentChangedFired(testObject, newParent1.Stories, false);

            testObject.FireParentChangedEvent = true;
            TestAssertParentChangedFired(testObject, newParent2.Stories, true);
        }

        [TestMethod]
        public override void TestParent()
        {
            Assert.IsNotNull(ToTest.Parent);
        }

        [TestMethod]
        public void TestTaskCollectionCount()
        {
            Assert.AreEqual(1, Context.Projects[Resources.Project1Id].Stories[Resources.UserStory1Id].Tasks.Count);
            Assert.AreEqual(2, Context.Projects[Resources.Project2Id].Stories[Resources.UserStory2Id].Tasks.Count);
            Assert.AreEqual(1, Context.Projects[Resources.Project1Id].Iterations[Resources.Iteration1Id].Stories[Resources.UserStory3Id].Tasks.Count);
            Assert.AreEqual(1, Context.Projects[Resources.Project1Id].Stories[Resources.UserStory4Id].Tasks.Count);
        }

        [TestMethod]
        public void TestStoriesAvailable()
        {
            Assert.AreEqual(Resources.FullUserStory1IdChain, Context.Projects[Resources.Project1Id].Stories[Resources.UserStory1Id].IdChain);
            Assert.AreEqual(Resources.FullUserStory2IdChain, Context.Projects[Resources.Project2Id].Stories[Resources.UserStory2Id].IdChain);
            Assert.AreEqual(Resources.FullUserStory3IdChain, Context.Projects[Resources.Project1Id].Iterations[Resources.Iteration1Id].Stories[Resources.UserStory3Id].IdChain);
            Assert.AreEqual(Resources.FullUserStory4IdChain, Context.Projects[Resources.Project1Id].Stories[Resources.UserStory4Id].IdChain);
        }

        [TestMethod]
        public void TestMemberIdGet()
        {
            Assert.AreEqual(DataObject[DataObjectSchema.MemberId], ToTest.AssignedMember.IdChain);
        }

        [TestMethod]
        public void TestMemberIdSet()
        {
            Member newMember = ToTest.Context.Projects[Resources.Project1Id].Members[Resources.Member2Id];
            ToTest.AssignedMember = newMember;
            Assert.AreEqual(DataObject[DataObjectSchema.MemberId], newMember.IdChain);
        }

        [TestMethod]
        public void TestRiskGet()
        {
            Assert.IsFalse(string.IsNullOrEmpty(ToTest[DataObjectSchema[TestFieldDefinitionSet.RiskFieldName]] as string));
        }

        [TestMethod]
        public void TestRiskSet()
        {
            string newRisk = "High";
            Assert.AreNotEqual(newRisk, ToTest[DataObjectSchema[TestFieldDefinitionSet.RiskFieldName]]);
            ToTest[DataObjectSchema[TestFieldDefinitionSet.RiskFieldName]] = newRisk;
            Assert.AreEqual(newRisk, DataObject[DataObjectSchema[TestFieldDefinitionSet.RiskFieldName]]);
        }

        [TestMethod]
        public void TestRiskMeta()
        {
            Assert.IsNotNull(ToTest.ItemType.FieldMeta.TryGetByName(TestFieldDefinitionSet.RiskFieldName));
            Assert.IsNotNull(ToTest.ItemType.FieldMeta.TryGetByName(TestFieldDefinitionSet.RiskFieldName).AllowedValues);
            Assert.IsTrue(ToTest.ItemType.FieldMeta.TryGetByName(TestFieldDefinitionSet.RiskFieldName).AllowedValues.ToEnumerable().Count() > 0);
        }

        [TestMethod]
        public void TestStateGet()
        {
            Assert.AreEqual(DataObject[DataObjectSchema.State], ToTest.State.ToString());
        }

        [TestMethod]
        public void TestStateSet()
        {
            TestStateSet(ActiveState, ClosedState);
            TestStateSet(ClosedState, InProgressState);
            TestStateSet(InProgressState, ToVerifyState);
            TestStateSet(ToVerifyState, ClosedState);
        }

        [TestMethod]
        public void TestStateSetWithUndoManager()
        {
            Assert.IsFalse(Context.UndoManager.CanUndo);
            TestStateSet(ActiveState, ToVerifyState);
            Assert.IsTrue(Context.UndoManager.CanUndo);
            TestStateSet(ToVerifyState, InProgressState);
            Assert.IsTrue(Context.UndoManager.CanUndo);
        }

        [TestMethod]
        public void TestStateReady()
        {
            Assert.IsTrue(!ToTest.ItemType.HasStrictWorkflow);
            Assert.IsTrue(ToTest.StateIsReady);

            ToTest.State = ToVerifyState;
            Assert.IsTrue(ToTest.StateIsReady);
            Assert.IsTrue(ToTest.CanChangeState(ClosedState));
        }

        /// <summary>
        /// Gets the default schema of the instance to test.
        /// </summary>
        /// <param name="schema">Specifies the parent schema instance.</param>
        /// <returns>Returns the retrieved schema instance.</returns>
        protected override UserStorySchema GetSchema(ScrumTableV1Schema schema)
        {
            return schema.UserStorySchema;
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}
